/*===================================================================

  Copyright (c) 1999
  Hewlett-Packard Company

  ATTENTION: USE OF THIS SOFTWARE IS SUBJECT TO THE FOLLOWING TERMS.
  Permission to use, copy, modify, distribute and/or sell this software 
  and/or its documentation is hereby granted without fee. User agrees 
  to display the above copyright notice and this license notice in all 
  copies of the software and any documentation of the software. User 
  agrees to assume all liability for the use of the software; Hewlett-Packard 
  makes no representations about the suitability of this software for any 
  purpose. It is provided "AS-IS without warranty of any kind,either express 
  or implied. User hereby grants a royalty-free license to any and all 
  derivatives based upon this software code base. 

		
  SNMP++ P D U _ C O N T . H

  PDU CONTAINER CLASS DEFINITION ( MS-WINDOWS 32 Only)


  VERSION
  2.8

  RCS INFO:
  $Header: pdu_cont.h,v 1.12 96/03/16 15:55:22 hmgr Exp $

  DESCRIPTION:
  This module contains the class definition for the pdu
  container class. The pdu conatiner is specific to the
  windows 3.1 implementation to allow multiple outstanding
  pdu requests.

  DESIGN:
  Peter E Mellquist

  AUTHOR:
  Peter E Mellquist

  LANGUAGE:
  ANSI C++

  OPERATING SYSTEM(S):
  Win32
  BSD UNIX


=====================================================================*/

#ifndef _PDU_CONT
#define _PDU_CONT

#include "winsnmp.h"   // windows snmp engine include
#include "smi.h"       // various smi defs

//------[ forward declarations ]-----------------------------
class Snmp;
class Pdu;
class SnmpTarget;

//--------[ Note!! ]------------------------------------------------------
// The following define determines the maximum number of outstanding
// pdu requests that an app can have. A sinlge machine may have multiple
// apps If an app has more than this number of outstanding requests, snmp access
// member functions will fail with a SNMP_CLASS_QUEUE_FULL error.
// This value may be increased depending on the apps demands.
//
#define MAX_PDU_SLOTS  300	  // maximum queue length of pdu container
#define MAX_REQUEST_ID 9000	  // starting request id
#define MIN_REQUEST_ID 10	  // ending request id, before reset to max

#ifdef _SNMPDEBUG
#define SNMPDEBUG(s)		   OutputDebugString(s)
#else
#define SNMPDEBUG(s)
#endif

//-----------[ callback typedef ]------------------------------------------
typedef void (WINFAR *snmpcallback)( int,	      // reason
				     Snmp*,	      // session handle
				     Pdu &,	      // pdu passsed in
				     SnmpTarget &,    // source target
				     void * ); // optional personality

//-----------[ pdu container class defs ]----------------------------------
//
// The pdu conatiner handles storage of all incoming pdus. Each Ssnmp object
// instance creates its own hidden window. When the session is created,
// the Win Snmp DLL is informed of the win proc. A common win proc is used
// to feed the pdu conatiner class. In this manner multiple concurrent
// blocked calls may be made.

// pdu container slot struct
// WinSnmp Specific


class Pdu_Slot
{
public:
  long int	    request_id;	   // associated request id
  int		    pending;	   // is this slot filled?
  int		    pdu_arrived;   // has the pdu arrived yet
  HSNMP_SESSION	    hSession;	   // WinSnmp Session handle
  HSNMP_ENTITY	    hSourceEntity; // Source Entity
  HSNMP_ENTITY	    hDestEntity;   // Destination Entity
  HSNMP_CONTEXT	    hRecContext;   // Receive Context
  smiINT	    PduType;	   // Type of pdu
  smiINT	    RequestId;	   // Request ID
  smiINT	    ErrorStatus;   // Error Status
  smiINT	    ErrorIndex;	   // Error Index
  snmpcallback	    callback;	   // callback function for async calls
  void *	    callback_data; // callback data
  HSNMP_VBL	    hRecVbl;	   // Received Variable Binding List
};


//------[ pdu container class ]-----------------------------------
class Pdu_Container {

public:

  // constructor
  // initialize all the slots to not pending
  // clear all the statistic counters
  Pdu_Container();

  // destructor
  ~Pdu_Container();


  // statistic mutator methods
  void pdu_sent()	  { pdus_sent++;};
  void pdu_received()	  { pdus_received++;};
  void trap_received()	  { trap_count++;};
  void traps_sent() { trap_sent++; }
  void decode_err()	  { decode_errors++;};
  void stray_response()	  { stray_responses++;};
  void invalid_resp_pdu() { invalid_pdu_types++;};
  void receive_err()	  { pdus_received_err++;};
  void sent_err()	  { pdus_sent_err++;};
  void timeout()	  { timeout_count++; };
  void set_max_queue( int z)
		      { if ( z > (int) max_queue_size)
			max_queue_size = ( unsigned long int) z; };

  // statistic accessor methods
  unsigned long int get_pdus_sent()	{ return pdus_sent; };
  unsigned long int get_pdus_received() { return pdus_received; };
  unsigned long int get_received_errs() { return pdus_received_err; };
  unsigned long int get_sent_errs()	{ return pdus_sent_err; };
  unsigned long int get_timeouts()	{ return timeout_count; };
  unsigned long int get_max_queue()	{ return max_queue_size; };
  unsigned long int get_trap_count()	{ return trap_count; };
  unsigned long int get_traps_sent()    { return trap_sent; }
  unsigned long int get_decode_errs()	{ return decode_errors; };
  unsigned long int get_inval_resp()	{ return invalid_pdu_types; };
  unsigned long int get_stray_resp()	{ return stray_responses; };


  // get a request id
  // this mf finds the first available slot and returns its
  // index value. The value is changed to reflect it is now
  // occupied. an error value is returned when no slots are
  // available
  // passed in rid may be passed back unless it is non-zero
  // calling get_request_id with 0 will cause a new unique
  // rid to be generated
  long int get_request_id( HSNMP_SESSION hSession, 
	                       snmpcallback cab,
			               void * cbd);

  // return a rid, don't save it in the pending table
  // used when sending a trap or any other non responsed pdu
  long int get_request_id();

  // clear the slot to make it available again
  void clear_request_id( const long int rid);

  // check if a pending pdu has arrived
  int check_if_arrived( const long int rid);

  // determine if a pdu slot is pending
  // received pdus are only placed into a slot
  // if it is pending
  int check_if_pending( const long int rid, snmpcallback *cb);

  void search_and_destroy( HSNMP_SESSION hSession, Snmp *snmp);

  // set a slot with an arrived pdu
  void set_slot( long int rid,			  // rid to set as arrived
		 HSNMP_SESSION	   hSession,	  // WinSnmp Session handle
		 HSNMP_ENTITY	   hSourceEntity, // Source Entity
		 HSNMP_ENTITY	   hDestEntity,	  // Destination Entity
		 HSNMP_CONTEXT	   hRecContext,	  // Receive Context
		 smiINT		   PduType,	  // Type of pdu
		 smiINT		   RequestId,	  // Request ID
		 smiINT		   ErrorStatus,	  // Error Status
		 smiINT		   ErrorIndex,	  // Error Index
		 HSNMP_VBL	   hRecVbl);	  // Received Variable Binding List

  // get the data from a slot
  //
  void get_slot( long int rid,		      // for this rid
	    HSNMP_ENTITY  *hSrcRecvEnt,	      // recieved source entity
	    HSNMP_ENTITY  *hDstRecvEnt,	      // recieved destination entity
	    HSNMP_CONTEXT *hRecvContext,      // recieved context
	    smiINT *lnRecvPduType,	          // type of pdu
	    smiINT *lnRecvRequestId,	      // request id
	    smiINT *lnErrorStatus,	          // error status
	    smiINT *lnErrorIndex,	          // error index
	    snmpcallback *cb,		          // callback funstion ptr
	    void * *cbd,		              // callback data
	    HSNMP_VBL *hRecvVbl);	          // recieved variable binding list

  // get callback information from a
  // given async call entry
  // returns true if an entryt was found
  // else returns false indicating no entry
  // was found for the requested rid
  int get_cb_info( long int rid,
		    snmpcallback *cb,
		    void * *cbd);

protected:
  Pdu_Slot *slots[MAX_PDU_SLOTS];	// slots for arrivals

  // statistics vars
  unsigned long int pdus_sent;		// total # of pdus sent
  unsigned long int pdus_received;	// total # of pdus received
  unsigned long int pdus_received_err;	// received error count
  unsigned long int pdus_sent_err;	// sent error count
  unsigned long int timeout_count;	// # of timeouts
  unsigned long int max_queue_size;	// maximum queue size
  unsigned long int trap_count;		// number of traps received
  unsigned long int trap_sent;      // number of traps sent
  unsigned long int decode_errors;	// number of snmp decode errors
  unsigned long int stray_responses;	// number of stray responses
  unsigned long int invalid_pdu_types;	// number of unided pdu types

  long int current_request_id;		// current request id

};

#endif //_PDU_CONT

